//
//  CircularLoaderView.swift
//  ImageLoaderIndicator
//
//  Created by apple on 16/5/30.
//  Copyright © 2016年 Rounak Jain. All rights reserved.
//

import UIKit

class CircularLoaderView: UIView {
 
    let circlePathLayer = CAShapeLayer()
    let circleRadius: CGFloat = 20.0
   
    //两个方法都进行了layer创建，保证了view可复用
    override init(frame: CGRect) {
        super.init(frame: frame)
        configure()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configure()
    }
    
    
    //MARK: - layer的创建
    func configure() {
        circlePathLayer.frame = bounds
        circlePathLayer.lineWidth = 2
        circlePathLayer.fillColor = UIColor.clearColor().CGColor
        circlePathLayer.strokeColor = UIColor.redColor().CGColor
        layer.addSublayer(circlePathLayer)
        backgroundColor = UIColor.whiteColor()
        progress = 0
    }
    
    
    //MARK: - 画圆的frame
    private func circleFrame() -> CGRect {
        var circleFrame = CGRect(x: 0, y: 0, width: 2*circleRadius, height: 2*circleRadius)
        circleFrame.origin.x = CGRectGetMidX(circlePathLayer.bounds) - CGRectGetMidX(circleFrame)
        circleFrame.origin.y = CGRectGetMidY(circlePathLayer.bounds) - CGRectGetMidY(circleFrame)
        return circleFrame
    }
    
    //MARK: - 画一个圆形的贝塞尔路径
    private func circlePath() -> UIBezierPath {
        return UIBezierPath(ovalInRect: circleFrame())
    }

    
    //MARK: 更新circlePathLayer的frame来恰当地响应view的size变化
    override func layoutSubviews() {
        super.layoutSubviews()
        circlePathLayer.frame = bounds
        circlePathLayer.path = circlePath().CGPath
    }
    
    //MARK: 画圆的过程
    
    var progress: CGFloat {
        get {
            return circlePathLayer.strokeEnd
        }
        set {
            if (newValue > 1) {
                circlePathLayer.strokeEnd = 1
            } else if (newValue < 0) {
                circlePathLayer.strokeEnd = 0
            } else {
                circlePathLayer.strokeEnd = newValue
            }
        }
    }
    
    
    func reveal() {
        
        // 1.设置view的背景色为clear，那么在view后面的image不再隐藏，然后设置progress为1或100%。
        backgroundColor = UIColor.clearColor()
        progress = 1
        
        
        // 2.使用strokeEnd属性来移除任何待定的implicit animations，否则干扰reveal animation。
        circlePathLayer.removeAnimationForKey("strokeEnd")
        
        
        // 3.从它的superLayer移除circlePathLayer，然后赋值给superView的layer maks，借助circular mask “hole”，image是可见的。这样让你复用已存在的layer和避免重复代码。
        circlePathLayer.removeFromSuperlayer()
        superview?.layer.mask = circlePathLayer
        
        
        // 1.确定圆形的半径之后就能完全限制image view。然后计算CGRect来完全限制这个圆形。toPath表示CAShapeLayer mask的最终形状。
        let center = CGPoint(x: CGRectGetMidX(bounds), y: CGRectGetMidY(bounds))
        let finalRadius = sqrt((center.x*center.x) + (center.y*center.y))
        let radiusInset = finalRadius - circleRadius
        let outerRect = CGRectInset(circleFrame(), -radiusInset, -radiusInset)
        let toPath = UIBezierPath(ovalInRect: outerRect).CGPath
        
        // 2.设置lineWidth和path初始值来匹配当前layer的值。
        let fromPath = circlePathLayer.path
        let fromLineWidth = circlePathLayer.lineWidth
        
        // 3.设置lineWidth和path的最终值；这样能防止它们当动画完成时跳回它们的原始值。CATransaction设置kCATransactionDisableActions键对应的值为true来禁用layer的implicit animations。
        CATransaction.begin()
        CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
        circlePathLayer.lineWidth = 2*finalRadius
        circlePathLayer.path = toPath
        CATransaction.commit()
        
        // 4.创建一个两个CABasicAnimation的实例，一个是路径动画，一个是lineWidth动画，lineWidth必须增加到两倍跟半径增长速度一样快，这样圆形向内扩展与向外扩展一样。
        let lineWidthAnimation = CABasicAnimation(keyPath: "lineWidth")
        lineWidthAnimation.fromValue = fromLineWidth
        lineWidthAnimation.toValue = 2*finalRadius
        let pathAnimation = CABasicAnimation(keyPath: "path")
        pathAnimation.fromValue = fromPath
        pathAnimation.toValue = toPath
        
        // 5.将两个animations添加到一个CAAnimationGroup，然后添加animation group到layer。将self赋值给delegate，等下你会使用到它。
        let groupAnimation = CAAnimationGroup()
        groupAnimation.duration = 1
        groupAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        groupAnimation.animations = [pathAnimation, lineWidthAnimation]
        groupAnimation.delegate = self
        circlePathLayer.addAnimation(groupAnimation, forKey: "strokeWidth")
    }
    
    
    override func animationDidStop(anim: CAAnimation, finished flag: Bool) {
        superview?.layer.mask = nil
    }
    
}
